package moodish.server;


import java.util.ArrayList;
import java.util.LinkedList;

import moodish.comm.ServerComm;
import moodish.comm.ServerSideMessage;
import moodish.server.MoodishServer;

/**
 * The server that:  keep track of who follows who and forward Mood messages accordingly; 
 * keep clients informed about who friends and unfriends them;
 * when a new client connects, the server send the list of currently connected user to that client so that the client will have an updated list of all currently connected users;
 * when a client connects or disconnects, the server sends a message with the appropriate information to all connected clients
 * @author Joao / Ricardo
 *
 */



public class ServerMain implements MoodishServer {


	ArrayList<User> listOfUsers = new ArrayList<User>();

	@Override
	public void start(ServerComm serverComm) {

		serverComm.start();
		


	while (true) {

		
		
		if (serverComm.hasNextMessage()){

			ServerSideMessage message = serverComm.getNextMessage();
				
				
/**
 * When a client connects, the server send one {@link moodish.comm.ClientSideMessage.Type#CONNECTED CONNECTED} message 
 * ({@link moodish.comm.ServerComm#sendClientConnected(String toNickname, String connectedNickname)
 * ServerComm.sendClientConnected()}) for each connected client so that the newly connected client can maintain a list 
 * of clients currently connected to the server. 
 */
				
			if (message.getType() == ServerSideMessage.Type.CLIENT_CONNECTED){

				
				boolean tempIsRegisteredUser = false;
	
				// Verifies if is registered user and if is, set him connected 
				for (User a: listOfUsers){
					if (a.getUser().equals(message.getClientNickname())){
						tempIsRegisteredUser = true;
						a.setConnected();
						

						LinkedList<String> listtemp = new LinkedList<String>();
						listtemp=a.getlistOffriends();
						
						for (String b: listtemp)
						{
							
							serverComm.sendClientConnected(a.getUser(), b.toString());
												
						}
					}
	
				}
	
	
				//If not registered, create a new User and sets Connected
				if (tempIsRegisteredUser == false){
	
					listOfUsers.add(new User(message.getClientNickname()));
					System.out.println("SERVER -->Just created a new User " + message.getClientNickname());
	
					for (User u:listOfUsers){
						if (u.getUser().equals(message.getClientNickname()))
							u.setConnected();
						
					}
					// send to client list of users connected
					for (User u: listOfUsers){
						if (u.getUser().equals(message.getClientNickname())){
							for (User x :listOfUsers){
								if(x.isConnected() && !u.getUser().equals(x.getUser()))
									
									serverComm.sendClientConnected(u.getUser(), x.getUser());
							}
						}
					}
				}
	
	
				//	Sends an sendClientConnected to all friends that are connected to the servers
	
				for (User u: listOfUsers){
	
					if (u.getUser().equals(message.getClientNickname())){
						
						
						LinkedList<String> listtemp = new LinkedList<String>();
						listtemp=u.getlistOffriends();
						
						for (String b: listtemp)
						{
							
							serverComm.sendClientConnected(b.toString(), message.getClientNickname());
											
						}
	
						
					}
				}
	
				
			}
			
/**
 * 
 *<p>
 * When a client disconnects, all clients should be sent a {@link moodish.comm.ClientSideMessage.Type#DISCONNECTED DISCONNECTED} message 
 * ({@link moodish.comm.ServerComm#sendClientDisconnected(String toNickname, String disconnectedNickname)
 * ServerComm.sendClientDisconnected()}). When a client disconnects, it loses all its friends and automatically
 * unfreinds all other clients. The server should thus not maintain a memory server regarding friends of disconnected clients. 
 */
			
			//checks if the message is type CLIENT_DISCONNECTED
			else if (message.getType() == ServerSideMessage.Type.CLIENT_DISCONNECTED){


				for (User u: listOfUsers){
					if (u.isConnected() && !u.getUser().equals(message.getClientNickname()))
						serverComm.sendClientDisconnected(u.getUser(),message.getClientNickname()); 
				}	

				//sets the user as disconnected and removes all list 
				for (User a:listOfUsers){
					if (a.getUser().equals(message.getClientNickname())){
						a.setDisconnect();

						System.out.println(" SERVER-->The user " + message.getClientNickname() + " is disconnecting");
						a.removeAllFriend();
						

					
					}	
				}
			}
	
			
	
			
			
			
			//checks if the message is type MOODISH_MESSAGE
			else if (message.getType().equals(ServerSideMessage.Type.MOODISH_MESSAGE)) {
	
	
				LinkedList<String> tempFriends = new LinkedList<String>();
	
	
				//return the list of Friends
				for (User a: listOfUsers){
	
	
					if (a.getUser().equals(message.getClientNickname())){
	
						tempFriends = a.getlistOffriends();
						
											
						for (String b: tempFriends)
						{
							//sends to all of his followers the message
							serverComm.sendMoodishMessage(message.getClientNickname(), b.toString(), message.getPayload());
							System.out.println("Lista de utilizadores " + b.toString());				
						}
	
					}
				}
	
	
				
			
			}

			

				//checks if the message is type
				else if (message.getType().equals(ServerSideMessage.Type.FRIENDSHIP)){


					for (User a: listOfUsers){
						if (a.getUser().equals(message.getClientNickname())){


							//If not in his list of Following, it add him to the list and sends a sendNewFollowers message.
							if (!a.inTheListofFriends(message.getPayload())){ 

								a.addfriend(message.getPayload());

								serverComm.sendNewFriendship(message.getPayload(), message.getClientNickname());
								
							}
							else
								//if in the list, it sends one error message
								serverComm.sendError(message.getClientNickname(), " Already following the requested user");

						}



					
					}


				}

				//checks if the message is type UNFRIENDSHIP
				else if (message.getType() == ServerSideMessage.Type.UNFRIENDSHIP){

					
					for (User a: listOfUsers){
						if (a.getUser().equals(message.getClientNickname())){

							//If is in the list of users he his following, it removes and sends a message sendNewUnfollow
							if(a.inTheListofFriends(message.getPayload())){
								a.removeFriend(message.getPayload());
								

								serverComm.sendNewUnfriendship(message.getPayload(), message.getClientNickname());
								
							}
							else
								//Of not in the list, sends one error message
								serverComm.sendError(message.getClientNickname(), " Not following the requested user");
						}
						
					}

				}

				else {
					//If it sends one message that has no Type than the others, it sends one erros message
					serverComm.sendError(message.getClientNickname(), "Erro - serviço solicitado não existente!!!!");
				}
			}
	}
	}

}
